package cn.thornbird.orgsync.helper;

import cn.thornbird.orgsync.entity.status.AppType;
import cn.thornbird.orgsync.helper.converter.DingTalkConverter;
import cn.thornbird.orgsync.model.AppUserData;
import cn.thornbird.orgsync.model.TreeData;
import cn.thornbird.orgsync.model.dingtalk.*;
import cn.thornbird.orgsync.util.JsonUtil;
import org.apache.commons.lang3.StringUtils;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.http.HttpHeaders;
import org.springframework.http.MediaType;

import java.nio.charset.StandardCharsets;
import java.util.*;
import java.util.stream.Collectors;

public class DingTalkHelper extends AppHelper<UserList.User> {

    public static final String API_HOST = "https://oapi.dingtalk.com";

    /**
     * <a href="https://open.dingtalk.com/document/orgapp/obtain-orgapp-token">获取企业内部应用的access_token</a>
     */
    public static final String GET_TOKEN_PATH = "/gettoken?appkey={appkey}&appsecret={appsecret}";

    /**
     * <a href="https://open.dingtalk.com/document/orgapp/obtain-enterprise-authentication-information">获取企业认证信息</a>
     */
    public static final String GET_AUTH_INFO_URL = "https://api.dingtalk.com/v1.0/contact/organizations/authInfos?targetCorpId={targetCorpId}";

    /**
     * <a href="https://open.dingtalk.com/document/orgapp/obtain-the-department-list-v2">获取部门列表</a>
     */
    public static final String GET_DEPARTMENT_LIST_PATH = "/topapi/v2/department/listsub?access_token={access_token}";

    /**
     * <a href="https://open.dingtalk.com/document/orgapp/query-department-details0-v2">获取部门详情</a>
     */
    public static final String GET_DEPARTMENT_DETAIL_PATH = "/topapi/v2/department/get?access_token={access_token}";

    /**
     * <a href="https://open.dingtalk.com/document/orgapp/queries-the-complete-information-of-a-department-user">获取部门用户详情</a>
     */
    public static final String GET_USER_LIST_PATH = "/topapi/v2/user/list?access_token={access_token}";

    /**
     * <a href="https://open.dingtalk.com/document/orgapp/query-user-details">查询用户详情</a>
     */
    public static final String GET_USER_PATH = "/topapi/v2/user/get?access_token={access_token}";

    /**
     * <a href="https://open.dingtalk.com/document/orgapp/query-users-by-phone-number">根据手机号查询用户</a>
     */
    public static final String GET_USER_ID_BY_MOBILE_PATH = "/topapi/v2/user/getbymobile?access_token={access_token}";

    /**
     * <a href="https://open.dingtalk.com/document/isvapp/address-book-search-user-id">搜索用户userId</a>
     */
    public static final String SEARCH_USER_PATH = "https://api.dingtalk.com/v1.0/contact/users/search";

    /**
     * <a href="https://open.dingtalk.com/document/orgapp/create-a-department-v2">创建部门</a>
     */
    public static final String CREATE_DEPARTMENT_PATH = "/topapi/v2/department/create?access_token={access_token}";

    /**
     * <a href="https://open.dingtalk.com/document/orgapp/update-a-department-v2">更新部门</a>
     */
    public static final String UPDATE_DEPARTMENT_PATH = "/topapi/v2/department/update?access_token={access_token}";

    /**
     * <a href="https://open.dingtalk.com/document/orgapp/delete-a-department-v2">删除部门</a>
     */
    public static final String DELETE_DEPARTMENT_PATH = "/topapi/v2/department/delete?access_token={access_token}";

    /**
     * <a href="https://open.dingtalk.com/document/orgapp/user-information-creation">创建用户</a>
     */
    public static final String CREATE_USER_PATH = "/topapi/v2/user/create?access_token={access_token}";

    /**
     * <a href="https://open.dingtalk.com/document/orgapp/user-information-update">更新用户信息</a>
     */
    public static final String UPDATE_USER_PATH = "/topapi/v2/user/update?access_token={access_token}";

    /**
     * <a href="https://open.dingtalk.com/document/orgapp/delete-a-user">删除用户</a>
     */
    public static final String DELETE_USER_PATH = "/topapi/v2/user/delete?access_token={access_token}";

    public static final String ZH_CN = "zh_CN";

    public static final String EN_US = "en_US";

    private String corpId;

    @Override
    public void initialize(RedisTemplate<String, String> redisTemplate, String certificateText) {
        super.initialize(redisTemplate, certificateText);
        Map<String, Object> map = JsonUtil.parseMap(certificateText);
        this.corpId = map.get("corpId").toString();
    }

    @Override
    public String getToken() {
        return new AccessTokenFactory().getAccessToken(AppType.DingTalk, certificateText).getToken(redisTemplate);
    }

    @Override
    public List<TreeData> getOrganizationTree() {
        List<TreeData> treeDataList = new ArrayList<>();
        AuthInfo authInfo = getAuthInfo();
        if (StringUtils.isEmpty(authInfo.getOrgName())) {
            return treeDataList;
        }

        TreeData item = new TreeData();
        item.setKey("1");
        item.setTitle(authInfo.getOrgName());
        treeDataList.add(item);
        DepartmentBaseList departmentBaseList = getDepartmentList(null);
        if (departmentBaseList.isSuccess()) {
            generateOrganizationTree(treeDataList, departmentBaseList.getResult(), item);
        }
        return treeDataList;
    }

    @Override
    public List<AppUserData> getUsersByDepartmentId(String departmentId) {
        List<AppUserData> users = new ArrayList<>();
        UserList userList = getUserList(departmentId == null ? null : Long.parseLong(departmentId), false);
        if (userList.isSuccess() && userList.getResult().getList() != null) {
            DingTalkConverter converter = new DingTalkConverter();
            for (UserList.User user : userList.getResult().getList()) {
                UserList.User userDetail = getUserDetail(user.getUserId());
                users.add(converter.parseUser(userDetail == null ? user : userDetail));
            }
        }
        return users;
    }

    @Override
    public AppUserData findAppUser(AppUserData sourceUser) {
        AppUserData targetUser = null;
        UserList.User user = getUser(UserAttr.MOBILE, sourceUser.getMobile());
        if (user == null) {
            user = getUser(UserAttr.NAME, sourceUser.getName());
        }
        if (user == null) {
            user = getUser(UserAttr.EMPLOYEE_NO, sourceUser.getEmployeeNo());
        }
        if (user == null) {
            user = getUser(UserAttr.EMAIL, sourceUser.getEmail());
        }
        if (user != null) {
            targetUser = new DingTalkConverter().parseUser(user);
        }
        return targetUser;
    }

    @Override
    public AppUserData findAppUserById(String id) {
        AppUserData targetUser = null;
        UserList.User user = getUser(UserAttr.ID, id);
        addUserDetail(user);
        if (user != null) {
            targetUser = new DingTalkConverter().parseUser(user);
        }
        return targetUser;
    }

    public AuthInfo getAuthInfo() {
        String token = getToken();
        HttpHeaders headers = new HttpHeaders();
        headers.add("x-acs-dingtalk-access-token", token);
        Map<String, Object> uriVariables = new HashMap<>();
        uriVariables.put("targetCorpId", corpId);
        return doGet(GET_AUTH_INFO_URL, headers, uriVariables, AuthInfo.class);
    }

    public DepartmentBaseList getDepartmentList(Long departmentId) {
        return getDepartmentBaseList(getToken(), departmentId, ZH_CN, true, null);
    }

    public DepartmentBaseList getDepartmentList(Long departmentId, String language) {
        return getDepartmentBaseList(getToken(), departmentId, language, true, null);
    }

    public DepartmentDetail getDepartmentDetail(Long departmentId) {
        return getDepartmentDetail(departmentId, ZH_CN);
    }

    public DepartmentDetail getDepartmentDetail(Long departmentId, String language) {
        String token = getToken();
        Map<String, Object> params = new HashMap<>();
        params.put("dept_id", departmentId);
        params.put("language", language);
        return doPost(GET_DEPARTMENT_DETAIL_PATH, params, token, DepartmentDetail.class);
    }

    public List<Long> getDepartmentIds(Long departmentId, DepartmentBaseList departmentBaseList) {
        List<Long> departmentIds = new ArrayList<>();
        departmentId = departmentId == null ? 1L : departmentId;
        departmentIds.add(departmentId);
        if (departmentBaseList.isSuccess() && departmentBaseList.getResult() != null) {
            departmentIds = departmentBaseList.getResult().stream().map(
                    DepartmentBaseList.DepartmentBase::getDeptId).collect(Collectors.toList());
            departmentIds.add(0, departmentId);
        }
        return departmentIds;
    }

    public UserList getUserList(Long departmentId, boolean fetchChild) {
        return getUserList(departmentId, ZH_CN, fetchChild);
    }

    public UserList getUserList(Long departmentId, List<Long> departmentIds) {
        return getUserList(departmentId, ZH_CN, departmentIds);
    }

    public UserList getUserList(Long departmentId, String language, boolean fetchChild) {
        String token = getToken();
        DepartmentBaseList departmentBaseList = getDepartmentBaseList(token, departmentId, language, fetchChild, null);
        List<Long> departmentIds = getDepartmentIds(departmentId, departmentBaseList);
        return getUserList(departmentId, language, departmentIds);
    }

    public UserList getUserList(Long departmentId, String language, List<Long> departmentIds) {
        String token = getToken();
        int count = departmentIds == null ? 0 : departmentIds.size();
        UserList userList = fetchUserList(token, departmentId, language, null, 0);
        Map<String, List<UserList.DepartmentOrder>> departmentOrderMap = new HashMap<>();
        Map<String, List<UserList.DepartmentLeader>> departmentLeaderMap = new HashMap<>();
        if (userList.getResult() != null && userList.getResult().getList() != null) {
            for (int i = 0, total = userList.getResult().getList().size(); i < total; i++) {
                UserList.User user = userList.getResult().getList().get(i);
                addUserToList(user, departmentId, departmentOrderMap, departmentLeaderMap, null);
            }
        }
        for (int i = 0; i < count; i++) {
            Long currentDepartmentId = departmentIds.get(i);
            UserList currentResult = fetchUserList(token, currentDepartmentId, language, null, 0);
            if (userList.getResult() != null && userList.getResult().getList() != null &&
                    currentResult.getResult() != null && currentResult.getResult().getList() != null) {
                for (int j = 0, total = currentResult.getResult().getList().size(); j < total; j++) {
                    UserList.User user = currentResult.getResult().getList().get(j);
                    addUserToList(user, currentDepartmentId, departmentOrderMap, departmentLeaderMap,
                            userList.getResult().getList());
                }
            }
        }
        return userList;
    }

    public UserList.User getUser(UserAttr userAttr, Object value) {
        return getUser(userAttr, value, ZH_CN);
    }

    public UserList.User getUser(UserAttr userAttr, Object value, String language) {
        UserList.User user = null;
        if (userAttr == null || value == null || StringUtils.isEmpty(value.toString())) {
            return user;
        }

        UserDetail userDetail = null;
        String id = null;
        String token = getToken();
        Map<String, Object> params = new HashMap<>();
        switch (userAttr) {
            case ID:
                params.put("userid", value);
                params.put("language", language);
                userDetail = doPost(GET_USER_PATH, params, token, UserDetail.class);
                break;
            case NAME:
                HttpHeaders headers = new HttpHeaders();
                headers.add("x-acs-dingtalk-access-token", token);
                headers.add(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_JSON_VALUE);
                params.put("queryWord", value.toString());
                params.put("offset", 0);
                params.put("size", 10);
                params.put("fullMatchField", 1);
                UserIdList userIdList = doPost(SEARCH_USER_PATH, headers, params, token, UserIdList.class);
                if (userIdList.getList() != null && userIdList.getList().size() == 1) {
                    id = userIdList.getList().get(0);
                }
                break;
            case MOBILE:
                params.put("mobile", getPureMobile(value.toString()));
                UserId userId = doPost(GET_USER_ID_BY_MOBILE_PATH, params, token, UserId.class);
                if (userId.isSuccess()) {
                    id = userId.getResult().getUserId();
                }
                break;
            case EMAIL:
            case ENTERPRISE_EMAIL:
            default:
                break;
        }
        if (id != null) {
            params.put("userid", id);
            params.put("language", language);
            userDetail = doPost(GET_USER_PATH, params, token, UserDetail.class);
        }
        if (userDetail != null && userDetail.isSuccess()) {
            user = userDetail.getResult();
        }
        if (userAttr == UserAttr.EMPLOYEE_NO || userAttr == UserAttr.EMAIL || userAttr == UserAttr.ENTERPRISE_EMAIL) {
            user = findUser(getAllUsers(), userAttr, value);
        }
        return user;
    }

    public UserList.User getUserDetail(String userId) {
        List<UserList.User> users = getAllUsers();
        UserList.User user = findUser(users, UserAttr.ID, userId);
        if (user != null && !user.isDetail()) {
            Map<String, Object> params = new HashMap<>();
            params.put("userid", userId);
            params.put("language", ZH_CN);
            UserDetail userDetail = doPost(GET_USER_PATH, params, getToken(), UserDetail.class);
            if (userDetail != null && userDetail.isSuccess()) {
                user = userDetail.getResult();
                addUserDetail(user);
            }
        }
        return user;
    }

    public List<UserList.User> getAllUsers() {
        List<UserList.User> users = null;
        if (allUsers == null) {
            UserList userList = getUserList(null, true);
            if (userList.isSuccess() && userList.getResult() != null) {
                users = userList.getResult().getList();
                allUsers = users;
            }
        } else {
            users = allUsers;
        }
        return users;
    }

    public DepartmentId createDepartment(String name, Long parentId, String sourceIdentifier, Long order,
                                         Boolean createDepartemntGroup) {
        String token = getToken();
        Map<String, Object> params = new HashMap<>();
        params.put("name", name);
        params.put("parent_id", parentId == null ? 1L : parentId);
        if (sourceIdentifier != null) {
            params.put("source_identifier", sourceIdentifier);
        }
        if (order != null) {
            params.put("order", order);
        }
        if (createDepartemntGroup != null) {
            params.put("create_dept_group", createDepartemntGroup);
        }
        return doPost(CREATE_DEPARTMENT_PATH, params, token, DepartmentId.class);
    }

    public Response updateDepartment(Long id, String name, Long parentId, String sourceIdentifier, Long order,
                                     Boolean createDepartemntGroup) {
        String token = getToken();
        Map<String, Object> params = new HashMap<>();
        params.put("dept_id", id);
        if (!StringUtils.isEmpty(name)) {
            params.put("name", name);
        }
        if (parentId != null) {
            params.put("parent_id", parentId);
        }
        if (sourceIdentifier != null) {
            params.put("source_identifier", sourceIdentifier);
        }
        if (order != null) {
            params.put("order", order);
        }
        if (createDepartemntGroup != null) {
            params.put("create_dept_group", createDepartemntGroup);
        }
        return doPost(UPDATE_DEPARTMENT_PATH, params, token, Response.class);
    }

    public Response deleteDepartment(Long id) {
        DepartmentBaseList departmentBaseList = getDepartmentList(id);
        List<Long> departmentIds = getDepartmentIds(id, departmentBaseList);
        UserList userList = getUserList(id, departmentIds);
        if (userList != null && userList.getResult() != null && userList.getResult().getList() != null) {
            for (UserList.User user : userList.getResult().getList()) {
                List<String> currentDepartmentIds = new ArrayList<>();
                List<String> userDepartmentIds = user.getDeptIdList();
                if (userDepartmentIds != null) {
                    for (String departmentId : userDepartmentIds) {
                        if (!departmentIds.contains(Long.parseLong(departmentId))) {
                            currentDepartmentIds.add(departmentId);
                        }
                    }
                }
                if (currentDepartmentIds.isEmpty()) {
                    currentDepartmentIds.add("1");
                }
                UserInfo userInfo = new UserInfo();
                userInfo.setUserId(user.getUserId());
                userInfo.setDeptIdList(currentDepartmentIds);
                updateUser(userInfo);
            }
        }
        if (departmentBaseList.isSuccess() && departmentBaseList.getResult() != null) {
            deleteSubdepartments(departmentBaseList, id, id);
        }
        String token = getToken();
        Map<String, Object> params = new HashMap<>();
        params.put("dept_id", id);
        return doPost(DELETE_DEPARTMENT_PATH, params, token, Response.class);
    }

    public UserId createUser(UserInfo userInfo) {
        return doPost(CREATE_USER_PATH, userInfo.toCreateParams(), getToken(), UserId.class);
    }

    public Response updateUser(UserInfo userInfo) {
        return doPost(UPDATE_USER_PATH, userInfo.toUpdateParams(), getToken(), Response.class);
    }

    public Response deleteUser(String userId) {
        String token = getToken();
        Map<String, Object> params = new HashMap<>();
        params.put("userid", userId);
        return doPost(DELETE_USER_PATH, params, token, Response.class);
    }

    public void removeCircularReference(String userId, String leaderId) {
        if (StringUtils.isEmpty(userId) || StringUtils.isEmpty(leaderId)) {
            return;
        }

        UserList.User user = getUserDetail(userId);
        if (user == null) {
            return;
        }

        UserList.User leader;
        while (true) {
            leader = getUserDetail(leaderId);
            if (leader == null || StringUtils.isEmpty(leader.getManagerUserId())) {
                break;
            }
            if (leader.getManagerUserId().equals(userId)) {
                UserInfo userInfo = new UserInfo();
                userInfo.setUserId(leaderId);
                userInfo.setManagerUserId("");
                updateUser(userInfo);
                break;
            }
            leaderId = leader.getManagerUserId();
        }
    }

    public <T> T doGet(String uri, Map<String, Object> uriVariables, String token, Class<T> clazz) {
        if (uriVariables != null && !StringUtils.isEmpty(token)) {
            uriVariables.put("access_token", token);
        }
        return doGet(hasScheme(uri) ? uri : API_HOST + uri, uriVariables, clazz);
    }

    public <T> T doPost(String uri, Map<String, Object> params, String token, Class<T> clazz) {
        HttpHeaders headers = new HttpHeaders();
        headers.setContentType(MediaType.APPLICATION_JSON);
        headers.add(HttpHeaders.CONTENT_ENCODING, StandardCharsets.UTF_8.toString());
        headers.add(HttpHeaders.ACCEPT, MediaType.APPLICATION_JSON_VALUE);
        return doPost(formatUri(API_HOST + uri, token), headers, params, clazz);
    }

    public <T> T doPost(String uri, HttpHeaders headers, Map<String, Object> params, String token, Class<T> clazz) {
        return doPost(formatUri(hasScheme(uri) ? uri : API_HOST + uri, token), headers, params, clazz);
    }

    @Override
    protected boolean checkUser(UserList.User user, UserAttr userAttr, Object value) {
        boolean result = false;
        switch (userAttr) {
            case ID:
                if (user.getUserId().equals(value)) {
                    result = true;
                }
                break;
            case EMPLOYEE_NO:
                if (user.getJobNumber() != null && user.getJobNumber().equals(value)) {
                    result = true;
                }
                break;
            case NAME:
                if (user.getName().equalsIgnoreCase(value.toString())) {
                    result = true;
                }
                break;
            case MOBILE:
                result = compareMobile(user.getMobile(), (String) value);
                break;
            case EMAIL:
                if (user.getEmail() != null && user.getEmail().equalsIgnoreCase(value.toString())) {
                    result = true;
                }
                break;
            case ENTERPRISE_EMAIL:
                if (user.getOrgEmail() != null && user.getOrgEmail().equalsIgnoreCase(value.toString())) {
                    result = true;
                }
                break;
            default:
                break;
        }
        return result;
    }

    private DepartmentBaseList getDepartmentBaseList(String token, Long departmentId, String language,
                                                     boolean fetchChild, DepartmentBaseList departmentBaseList) {
        boolean flag = departmentBaseList == null;
        Map<String, Object> params = new HashMap<>();
        params.put("dept_id", departmentId == null ? 1L : departmentId);
        params.put("language", language);
        DepartmentBaseList currentResult = doPost(GET_DEPARTMENT_LIST_PATH, params, token, DepartmentBaseList.class);
        if (!currentResult.isSuccess()) {
            departmentBaseList = currentResult;
            return departmentBaseList;
        }

        if (flag) {
            departmentBaseList = currentResult;
        }
        if (!fetchChild) {
            return departmentBaseList;
        }

        if (currentResult.getResult() == null || currentResult.getResult().size() == 0) {
            return departmentBaseList;
        }

        if (!flag) {
            departmentBaseList.getResult().addAll(currentResult.getResult());
        }
        for (int i = 0, count = currentResult.getResult().size(); i < count; i++) {
            DepartmentBaseList.DepartmentBase departmentBase = currentResult.getResult().get(i);
            getDepartmentBaseList(token, departmentBase.getDeptId(), language, true, departmentBaseList);
        }
        return departmentBaseList;
    }

    private UserList fetchUserList(String token, Long departmentId, String language, UserList userList, int cursor) {
        boolean flag = userList == null;
        Map<String, Object> params = new HashMap<>();
        params.put("dept_id", departmentId == null ? 1L : departmentId);
        params.put("language", language);
        params.put("cursor", cursor);
        params.put("size", 100);
        params.put("order_field", "entry_asc");
        params.put("contain_access_limit", true);
        UserList currentResult = doPost(GET_USER_LIST_PATH, params, token, UserList.class);
        if (flag) {
            userList = currentResult;
        }
        if (currentResult.getResult() == null || currentResult.getResult().getList() == null ||
                currentResult.getResult().getList().size() == 0) {
            return userList;
        }

        if (!flag) {
            userList.getResult().getList().addAll(currentResult.getResult().getList());
        }
        if (currentResult.getResult().getHasMore() != null && currentResult.getResult().getHasMore() &&
                currentResult.getResult().getNextCursor() != null) {
            fetchUserList(token, departmentId, language, userList, currentResult.getResult().getNextCursor().intValue());
        }
        return userList;
    }

    private void generateOrganizationTree(List<TreeData> treeDataList,
                                          List<DepartmentBaseList.DepartmentBase> departments, TreeData parent) {
        for (int i = 0, count = departments.size(); i < count; i++) {
            DepartmentBaseList.DepartmentBase department = departments.get(i);
            if (department.getParentId().equals(Long.valueOf(parent.getKey()))) {
                TreeData item = new TreeData();
                item.setKey(department.getDeptId().toString());
                item.setTitle(department.getName());
                if (parent.getChildren() == null) {
                    parent.setChildren(new ArrayList<>());
                }
                parent.getChildren().add(item);
                generateOrganizationTree(treeDataList, departments, item);
            }
        }
    }

    private void addUserToList(UserList.User user, Long departmentId,
                               Map<String, List<UserList.DepartmentOrder>> departmentOrderMap,
                               Map<String, List<UserList.DepartmentLeader>> departmentLeaderMap,
                               List<UserList.User> userList) {
        boolean flag = false;

        List<UserList.DepartmentOrder> orders;
        if (departmentOrderMap.containsKey(user.getUserId())) {
            orders = departmentOrderMap.get(user.getUserId());
        } else {
            flag = true;
            orders = new ArrayList<>();
            departmentOrderMap.put(user.getUserId(), orders);
        }
        UserList.DepartmentOrder order = new UserList.DepartmentOrder();
        order.setDeptId(departmentId == null ? 1L : departmentId);
        order.setOrder(user.getDeptOrder());
        orders.add(order);
        if (user.getDeptIdList() != null && orders.size() == user.getDeptIdList().size()) {
            Collections.sort(orders, (o1, o2) -> {
                int index1 = user.getDeptIdList().indexOf(o1.getDeptId());
                int index2 = user.getDeptIdList().indexOf(o2.getDeptId());
                return index1 - index2;
            });
        }
        user.setDeptOrderList(orders);
        user.setDeptOrder(null);

        List<UserList.DepartmentLeader> leaders;
        if (departmentLeaderMap.containsKey(user.getUserId())) {
            leaders = departmentLeaderMap.get(user.getUserId());
        } else {
            flag = true;
            leaders = new ArrayList<>();
            departmentLeaderMap.put(user.getUserId(), leaders);
        }
        UserList.DepartmentLeader leader = new UserList.DepartmentLeader();
        leader.setDeptId(departmentId == null ? 1L : departmentId);
        leader.setLeader(user.getLeader());
        leaders.add(leader);
        if (user.getDeptIdList() != null && leaders.size() == user.getDeptIdList().size()) {
            Collections.sort(leaders, (o1, o2) -> {
                int index1 = user.getDeptIdList().indexOf(o1.getDeptId());
                int index2 = user.getDeptIdList().indexOf(o2.getDeptId());
                return index1 - index2;
            });
        }
        user.setLeaderInDept(leaders);
        user.setLeader(null);

        if (flag && userList != null) {
            userList.add(user);
        }
    }

    private void addUserDetail(UserList.User user) {
        if (allUsers != null && user != null) {
            user.setDetail(true);
            for (int i = 0, count = allUsers.size(); i < count; i++) {
                if (allUsers.get(i).getUserId().equals(user.getUserId())) {
                    allUsers.set(i, user);
                    break;
                }
            }
        }
    }

    private void deleteSubdepartments(DepartmentBaseList departmentBaseList, Long parentId, Long rootId) {
        List<Long> ids = new ArrayList<>();
        for (DepartmentBaseList.DepartmentBase department : departmentBaseList.getResult()) {
            if (department.getParentId() != null && department.getParentId().equals(parentId)) {
                ids.add(department.getDeptId());
            }
        }
        for (Long id : ids) {
            deleteSubdepartments(departmentBaseList, id, rootId);
        }
        if (!parentId.equals(rootId)) {
            String token = getToken();
            Map<String, Object> params = new HashMap<>();
            params.put("dept_id", parentId);
            doPost(DELETE_DEPARTMENT_PATH, params, token, Response.class);
        }
    }

}
